後端系統其實最核心的就是與資料庫進行互動,我在寫rails時有一個module就是負責與資料庫的互動- ActiveRecord
,這個module
最核心的就是把record
包裝成實體物件,也可以說是映射到ruby的物件上,於是乎,我就可以很方便的處理這些物件,我很依賴這樣子的處理方式,但必須說,這前提都是建立在物件導向語言上
然而,要知道go並不是一個物件導向語言,Go 傾向於提供較少的特性,並強調簡單和效能。這些特性使得 Go 在某些方面(例如並發)表現出色,但在其他方面(例如物件關聯映射(ORM))可能不是那麼直觀或易用,像是ORM
故,再go的後端系統上選擇實作orm時,一定要考慮這些問題
但好在,現在有一個穩定的orm package,今天我們就要來介紹這個package
gorm 是一個用於 Go 語言的 Object Relational Mapping (ORM) 庫,它封裝了 database/sql 的許多功能,並提供了一個更高級的接口來與數據庫進行交互
所以前幾天說到的database/sql的功能,我們會依賴gorm 來幫我們完成
db docking:
package main
import (
"gorm.io/gorm"
"gorm.io/driver/sqlite"
)
db open:
func main() {
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
}
接下來我們來看看基本用法吧
在 GORM中,當我們談到"模型",我們通常是指用來代表和操作數據庫表的 Go 結構體。這些結構體包含一些字段,這些字段的類型通常是:
基本 Go 類型:例如 string
、int
、float64
等,用於儲存常見的數據類型
指針或別名:例如 *string
或 *int
,允許字段為 nil
,在數據庫中表示為 NULL
值,別名就是你為現有的類型定義的一個新名字,例如 type Age int
。
自定義類型:這些類型實現了 Scanner
和 Valuer
接口,允許你自定義如何將數據讀取到 Go 程序中(Scanner
)和如何將 Go 程序中的數據保存到數據庫中(Valuer
),這對於處理數據庫中的特殊類型(例如 JSON、ENUM 等)或執行自定義數據處理非常有用。
type User struct {
ID uint
Name string
Email *string
Age uint8
Birthday *time.Time
MemberNumber sql.NullString
ActivatedAt sql.NullTime
CreatedAt time.Time
UpdatedAt time.Time
}
GORM 傾向於選擇慣例優於配置,默認情況下,GORM 使用 ID 作為主鍵,將結構名複數化並轉換為 snake_case 作為表名,使用 snake_case 作為列名,並使用 CreatedAt 和 UpdatedAt 來表示建立時間/更新時間
這是GORM的慣例,當然也可以打破慣例,可以多參考官方的說明書
PostgreSQL
import (
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
dsn := "host=localhost user=gorm password=gorm dbname=gorm port=9920 sslmode=disable TimeZone=Asia/Shanghai"
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
user := User{Name: "Jinzhu", Age: 18, Birthday: time.Now()}
result := db.Create(&user) // pass pointer of data to Create
user.ID // returns inserted data's primary key
result.Error // returns error
result.RowsAffected // returns inserted records count
GORM 提供了 First、Take 和 Last 方法來實現這一點,並在查詢數據庫時添加了 LIMIT 1 條件。如果沒有找到記錄,它將返回 ErrRecordNotFound 錯誤
也提供where查詢
// Get first matched record
db.Where("name = ?", "jinzhu").First(&user)
// SELECT * FROM users WHERE name = 'jinzhu' ORDER BY id LIMIT 1;
// Get all matched records
db.Where("name <> ?", "jinzhu").Find(&users)
// SELECT * FROM users WHERE name <> 'jinzhu';
// IN
db.Where("name IN ?", []string{"jinzhu", "jinzhu 2"}).Find(&users)
// SELECT * FROM users WHERE name IN ('jinzhu','jinzhu 2');
// LIKE
db.Where("name LIKE ?", "%jin%").Find(&users)
// SELECT * FROM users WHERE name LIKE '%jin%';
// AND
db.Where("name = ? AND age >= ?", "jinzhu", "22").Find(&users)
// SELECT * FROM users WHERE name = 'jinzhu' AND age >= 22;
db.First(&user)
user.Name = "jinzhu 2"
user.Age = 100
db.Save(&user)
// UPDATE users SET name='jinzhu 2', age=100, birthday='2016-01-01', updated_at = '2013-11-17 21:34:10' WHERE id=111;
// Email's ID is `10`
db.Delete(&email)
// DELETE from emails where id = 10;
// Delete with additional conditions
db.Where("name = ?", "jinzhu").Delete(&email)
// DELETE from emails where id = 10 AND name = "jinzhu";
示例參考 gorm